/**
 * @file spi_ws2812.c
 * @author your name (you@domain.com)
 * @brief
 * @version 0.1
 * @date 2025-07-07
 *
 * @copyright Copyright (c) 2025
 *
 */
#include "spi_ws2812.h"
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

static void __build_led_color_data(ws2812b_t *ws2812b);
static color_t hsv_to_rgb(hsv_color_t hsv);
static void ws2812_gpio_init(uint8_t pin)
{
	struct bflb_device_s *gpio;

	gpio = bflb_device_get_by_name("gpio");

	bflb_gpio_init(gpio, DEFAULT_SPI_CLK, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
	bflb_gpio_init(gpio, DEFAULT_SPI_MISO, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
	bflb_gpio_init(gpio, pin, GPIO_FUNC_SPI0 | GPIO_ALTERNATE | GPIO_PULLUP | GPIO_SMT_EN | GPIO_DRV_1);
}
void ws2812b_init(ws2812b_t *ws2812b, uint8_t ws2812_dat_pin)
{
	if (ws2812b == NULL)
	{
		return;
	}
	// 初始化SPI设备
	ws2812_gpio_init(ws2812_dat_pin);
	struct bflb_spi_config_s spi_cfg = {
#if (SPI_CASE_SELECT == SPI_MASTER_CASE)
		.freq = 8000000, // 8MHz
		.role = SPI_ROLE_MASTER,
#else
		.freq = 32 * 1000 * 1000,
		.role = SPI_ROLE_SLAVE,
#endif
		.mode = SPI_MODE3,
		.data_width = SPI_DATA_WIDTH_8BIT,
		.bit_order = SPI_BIT_MSB,
		.byte_order = SPI_BYTE_LSB,
		.tx_fifo_threshold = 0,
		.rx_fifo_threshold = 0,
	};
	ws2812b->sw2812_spi = bflb_device_get_by_name(DEFAULT_SPI_DIRVER);
	bflb_spi_init(ws2812b->sw2812_spi, &spi_cfg);
	// 分配24位颜色数据内存
	ws2812b->color_datas = (uint8_t *)malloc(
		ws2812b->led_counts * BITS_PER_LED_COLOR + 32);
	// 分配LED颜色数据内存
	ws2812b->led_colors = (color_t *)malloc(
		sizeof(color_t) * ws2812b->led_counts);

	if (ws2812b->color_datas && ws2812b->led_colors)
	{
		ws2812b->inited = true;
		ws2812b->color_data_size = ws2812b->led_counts * BITS_PER_LED_COLOR; //+32
	}
	else
	{
		ws2812b->inited = false;
	}
}

// 生成24位颜色数据序列
static void __build_led_color_data(ws2812b_t *ws2812b)
{
	if (ws2812b == NULL)
	{
		return;
	}
	for (int i = 0; i < ws2812b->led_counts; i++)
	{
		uint8_t m = 0b10000000;
		for (int b = 0; b < 8; b++)
		{
			ws2812b->color_datas[BITS_PER_LED_COLOR * i + b] =
				ws2812b->led_colors[i].g & m ? SPI_NEO1 : SPI_NEO0;
			m >>= 1u;
		}

		m = 0b10000000;
		for (int b = 0; b < 8; b++)
		{
			ws2812b->color_datas[BITS_PER_LED_COLOR * i + b + 8] =
				ws2812b->led_colors[i].r & m ? SPI_NEO1 : SPI_NEO0;
			m >>= 1u;
		}

		m = 0b10000000;
		for (int b = 0; b < 8; b++)
		{
			ws2812b->color_datas[BITS_PER_LED_COLOR * i + b + 16] =
				ws2812b->led_colors[i].b & m ? SPI_NEO1 : SPI_NEO0;
			m >>= 1u;
		}
	}
}

void ws2812b_set_color(ws2812b_t *ws2812b, uint16_t index, color_t color)
{
	if (index >= ws2812b->led_counts && ws2812b->inited)
	{
		return;
	}
	ws2812b->led_colors[index] = color;
}

void ws2812b_show(ws2812b_t *ws2812b)
{
	if (ws2812b == NULL && !ws2812b->inited && ws2812b->sw2812_spi == NULL)
	{
		printf("\033[31m ERROR:ws2812b not inited\033[0m\r\n");
		return;
	}
	
	__build_led_color_data(ws2812b);
	for (int i = 0; i < ws2812b->color_data_size; i++)
	{
		bflb_spi_poll_send(ws2812b->sw2812_spi, ws2812b->color_datas[i]);
	}
}

// HSV转RGB实现
static color_t hsv_to_rgb(hsv_color_t hsv)
{
	color_t rgb = {0, 0, 0};
	float r, g, b;
	float c = hsv.v * hsv.s;
	float x = c * (1 - fabs(fmod(hsv.h / 60.0, 2) - 1));
	float m = hsv.v - c;

	if (hsv.h >= 0 && hsv.h < 60)
	{
		r = c;
		g = x;
		b = 0;
	}
	else if (hsv.h >= 60 && hsv.h < 120)
	{
		r = x;
		g = c;
		b = 0;
	}
	else if (hsv.h >= 120 && hsv.h < 180)
	{
		r = 0;
		g = c;
		b = x;
	}
	else if (hsv.h >= 180 && hsv.h < 240)
	{
		r = 0;
		g = x;
		b = c;
	}
	else if (hsv.h >= 240 && hsv.h < 300)
	{
		r = x;
		g = 0;
		b = c;
	}
	else if (hsv.h >= 300 && hsv.h < 360)
	{
		r = c;
		g = 0;
		b = x;
	}

	rgb.r = (uint8_t)((r + m) * 255);
	rgb.g = (uint8_t)((g + m) * 255);
	rgb.b = (uint8_t)((b + m) * 255);

	return rgb;
}
// 设置HSV颜色
void ws2812b_set_hsv_color(ws2812b_t *ws2812b, uint16_t led_index, hsv_color_t hsv)
{
	if (!ws2812b->inited || led_index >= ws2812b->led_counts)
	{
		return;
	}

	color_t rgb = hsv_to_rgb(hsv);
	ws2812b_set_color(ws2812b, led_index, rgb);
}

// 设置整条灯带为炫彩效果
void ws2812b_set_rainbow(ws2812b_t *ws2812b, uint8_t brightness)
{
	if (!ws2812b->inited)
	{
		return;
	}

	for (uint16_t i = 0; i < ws2812b->led_counts; i++)
	{
		// 计算当前LED的色相值 (0-360)
		float hue = fmod(ws2812b->rainbow_offset + (i * 360.0 / ws2812b->led_counts), 360.0);

		// 创建HSV颜色 (饱和度为1，亮度为传入参数/255)
		hsv_color_t hsv = {hue, 1.0, brightness / 255.0};

		// 设置LED颜色
		ws2812b_set_hsv_color(ws2812b, i, hsv);
	}

	// 更新偏移量用于下一次调用
	ws2812b->rainbow_offset = (ws2812b->rainbow_offset + 1) % 360;
}

// 炫彩循环动画
void ws2812b_rainbow_cycle(ws2812b_t *ws2812b, uint8_t brightness, uint8_t wait_ms)
{
	ws2812b_set_rainbow(ws2812b, brightness);
	ws2812b_show(ws2812b);
	bflb_mtimer_delay_ms(wait_ms);
}